

#include "ServerTask.h"

#include <event2/listener.h>

#include <iostream>
#include <memory>

#include "FileServerTask.h"
#include "ThreadPool.h"

#ifdef _WIN32
#  include <windows.h>
#  include <winsock2.h>
#else
#  include <arpa/inet.h>
#  include <sys/socket.h>
#endif

namespace ZeDisk {

static void _accept_cb(evconnlistener *listen, evutil_socket_t fd,
                       sockaddr *sin, int socklen, void *user_data) {
  auto task = reinterpret_cast<ServerTask *>(user_data);
  task->AcceptCallback(fd, sin, socklen);
}

bool ServerTask::Init() {
  // 监听端口
  sockaddr_in sin = {0};
  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = htonl(INADDR_ANY);
  sin.sin_port = htons(server_port_);

  // 设置回调函数
  auto listener = evconnlistener_new_bind(
      base_, _accept_cb, this, LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE, -1,
      (sockaddr *)&sin, sizeof(sin));

  if (!listener) {
    std::cout << "[ERROR] evconnlistener_new_bind() failed" << std::endl;
    return false;
  }
  std::cout << "[INFO] Listening on port " << server_port_ << std::endl;

  return true;
}

bool ServerTask::Stop() {
  return true;
}

void ServerTask::AcceptCallback(int fd, sockaddr *sin, int socklen) {
#ifdef DEBUG
  std::cout << "[DEBUG] ServerTask Accept ip: "
            << inet_ntoa(((sockaddr_in *)sin)->sin_addr) << ":"
            << ntohs(((sockaddr_in *)sin)->sin_port) << std::endl;
#endif
  auto task = std::make_shared<FileServerTask>();
  task->sockfd() = fd;
  threadpool_->Dispatch(task);
}

}  // namespace ZeDisk